//
//  JSQShowImageScrollView.m
//  Conversation
//
//  Created by C_HAO on 15/10/16.
//  Copyright © 2015年 CHAOO. All rights reserved.
//

#import "JSQShowImageScrollView.h"

#define ScreenWidth      [UIScreen mainScreen].bounds.size.width
#define ScreenHeight     [UIScreen mainScreen].bounds.size.height

@interface JSQShowImageScrollView () <UIScrollViewDelegate>

@property(nonatomic, assign) NSInteger currentIndex;

@property(nonatomic, strong) NSMutableArray *visibleViews;

@property(nonatomic, strong) NSMutableDictionary *reuseViews;

@end


@implementation JSQShowImageScrollView

- (instancetype)initWithFrame:(CGRect)frame withIndex:(NSInteger)index {
    self = [super initWithFrame:frame];
    if (self) {

        // 设置代理
        self.delegate = self;
        // 不显示滚动条
        self.showsHorizontalScrollIndicator = NO;
        self.showsVerticalScrollIndicator = NO;
        // 设置分页显示
        self.pagingEnabled = YES;
        //设置背景颜色
        self.backgroundColor = [UIColor clearColor];

        [self setup];

        self.contentOffset = CGPointMake(ScreenWidth * index, 0);

    }
    return self;
}

#pragma mark - Instance Method

- (instancetype)dequeueReusableViewWithIdentifier:(NSString *)identifier {
    if (![[self.reuseViews allKeys] containsObject:identifier]) {
        return nil;
    }

    NSMutableSet *set = self.reuseViews[identifier];

    id reuseView = [set anyObject];

    if (reuseView) {
        [set removeObject:reuseView];
    }



    return reuseView;
}

- (void)reloadData {
    [self resetScrollViewContentSize];
    [self reuseAllView];
    [self refreshView];
}

- (void)showDesignationPage:(NSInteger)page {
    dispatch_async(dispatch_get_main_queue(), ^{

        self.contentOffset = CGPointMake(ScreenWidth * page, 0);
    });

}

#pragma mark - Reuse Method

- (void)reuseViewIfNeeded {
    NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet];
    for (int i = 0; i < self.visibleViews.count; i++) {
        JSQShowZoomImageScrollView *view = self.visibleViews[i];
        if ([self checkIfViewNeedReuse:view]) {
            [self reuseViewIntoSet:view];
            [indexSet addIndex:i];
        }
    }

    if (indexSet.count) {
        [self.visibleViews removeObjectsAtIndexes:indexSet];
    }
}

- (void)reuseAllView {
    for (JSQShowZoomImageScrollView *view in self.visibleViews) {
        [self reuseViewIntoSet:view];
    }
    [self.visibleViews removeAllObjects];
}

- (void)reuseViewIntoSet:(JSQShowZoomImageScrollView *)view {
    if (view.superview) {
        [view removeFromSuperview];
    }

    if ([[self.reuseViews allKeys] containsObject:view.identifier]) {
        NSMutableSet *set = self.reuseViews[view.identifier];
        [set addObject:view];
    } else {
        NSMutableSet *set = [NSMutableSet set];
        [set addObject:view];
        [self.reuseViews setObject:set forKey:view.identifier];
    }
}

- (BOOL)checkIfViewNeedReuse:(JSQShowZoomImageScrollView *)view {
    NSInteger indexOffset = view.index - self.currentIndex;
    indexOffset = indexOffset < 0 ? indexOffset * -1 : indexOffset;

    if (indexOffset > self.preloadNum) {
        return YES;
    }
    return NO;
}

#pragma mark - Reset Method

- (void)loadNearbyView {
    NSInteger beginIndex = self.currentIndex - self.preloadNum;
    beginIndex = beginIndex < 0 ? 0 : beginIndex;

    NSInteger endIndex = self.currentIndex + self.preloadNum;
    NSInteger itemCount = [self numberOfItems];
    endIndex = endIndex >= itemCount ? itemCount - 1 : endIndex;

    for (NSInteger i = beginIndex; i <= endIndex; i++) {
        int hasFound = NO;
        for (JSQShowZoomImageScrollView *view in self.visibleViews) {

            if (view.index == i) {
                hasFound = YES;
                break;
            }
        }

        if (!hasFound) {
            [self addViewToIndex:i];
        }
    }
}

- (void)refreshView {
    NSInteger beginIndex = self.currentIndex - self.preloadNum;
    beginIndex = beginIndex < 0 ? 0 : beginIndex;

    NSInteger endIndex = self.currentIndex + self.preloadNum;
    NSInteger itemCount = [self numberOfItems];
    endIndex = endIndex >= itemCount ? itemCount - 1 : endIndex;

    for (NSInteger i = beginIndex; i <= endIndex; i++) {
        [self addViewToIndex:i];
    }
}

- (JSQShowZoomImageScrollView *)addViewToIndex:(NSInteger)index {
    JSQShowZoomImageScrollView *view = [self.imageDataSource scrollView:self viewForItemAtIndex:index];

    view.index = index;

    UIEdgeInsets inset = [self insetForIndex:index];

    view.frame = CGRectMake(CGRectGetWidth(self.bounds) * index + inset.left,
                            inset.top,
                            CGRectGetWidth(self.bounds) - inset.right - inset.left,
                            CGRectGetHeight(self.bounds) - inset.bottom - inset.top);
    [self addSubview:view];

    [self.visibleViews addObject:view];

    return view;
}

#pragma mark - Utility Method

- (void)resetScrollViewContentSize {
    NSInteger count = [self numberOfItems];
    self.contentSize = CGSizeMake(CGRectGetWidth(self.bounds) * count, CGRectGetHeight(self.bounds));
}

- (NSInteger)numberOfItems {
    if (self.imageDataSource
        && [self.imageDataSource respondsToSelector:@selector(numberOfItemsInScrollView:)]) {
        return [self.imageDataSource numberOfItemsInScrollView:self];
    }

    return 0;
}

- (UIEdgeInsets)insetForIndex:(NSInteger)index {
    if (self.imageDelegate
        && [self.imageDelegate respondsToSelector:@selector(scrollView:insetForForItemAtIndex:)]) {
        return [self.imageDelegate scrollView:self insetForForItemAtIndex:index];
    }
    return self.reuseViewInset;
}

#pragma mark Target/Action

- (void)scrollViewDidScrollWithOffset:(CGPoint)offset {
    NSInteger index = offset.x / CGRectGetWidth(self.bounds);
    if (index < 0) {
        index = 0;
    }

    NSInteger itemCount = [self numberOfItems];
    if (index >= itemCount) {
        index = itemCount - 1;
    }

    if (self.currentIndex != index) {
        self.currentIndex = index;
        [self reuseViewIfNeeded];
        [self loadNearbyView];
    }

}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"contentOffset"]) {
        CGPoint offset = [change[NSKeyValueChangeNewKey] CGPointValue];
        [self scrollViewDidScrollWithOffset:offset];
    } else if ([keyPath isEqualToString:@"frame"]) {
        [self reloadData];
    }
}

#pragma mark - Init Method

- (void)setup {
    self.visibleViews = [NSMutableArray array];
    self.reuseViews = [NSMutableDictionary dictionary];

    self.reuseViewInset = UIEdgeInsetsMake(0, 0, 0, 0);
    self.preloadNum = 1;

    [self addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
    [self addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)stop {
    [self removeObserver:self forKeyPath:@"contentOffset" context:nil];
    [self removeObserver:self forKeyPath:@"frame" context:nil];
}

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {

    [self.visibleViews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

        [(JSQShowZoomImageScrollView *) obj setZoomScale:1 animated:YES];

    }];


    if (_slideScrollPage) {
        _slideScrollPage((NSInteger)(targetContentOffset->x/ScreenWidth)+1);
    }

}

@end
